﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sinacor.Infra.Common.Security.Services
{
    public class ChannelCache
    {
        Dictionary<string, ChannelEntity> _list = new Dictionary<string, ChannelEntity>();

        static ChannelCache _instance;

        private ChannelCache()
        { 
        }

        public static ChannelCache GetInstance()
        {
            if (_instance == null)
                _instance = new ChannelCache();

            return _instance;
        }

        public void Add<T>(string endpoint, SinacorClientChannel<T> serviceChannel, T instance)
        {
            if (!_list.ContainsKey(endpoint))
            {
                ChannelEntity<T> ce = new ChannelEntity<T>();
                ce.Endpoint = endpoint;
                ce.ServiceChannel = serviceChannel;
                ce.instance = instance;
                ce.CreateTime = DateTime.Now;
                _list.Add(typeof(T).FullName, ce);
            }
        }

        public T Retrieve<T>(string endpoint) 
        {
            //Verifica se existe na collection
            //if (_list.ContainsKey(endpoint))
            if (_list.ContainsKey(typeof(T).FullName))
            {
                ChannelEntity<T> entity = (ChannelEntity<T>)_list[typeof(T).FullName];
                System.ServiceModel.ICommunicationObject obj = entity.instance as System.ServiceModel.ICommunicationObject;

                //Se o canal continuar aberto e o tempo de criação dele for menor que 30 minutos.
                if (obj.State == System.ServiceModel.CommunicationState.Opened && entity.CreateTime.AddMinutes(30) > DateTime.Now)
                    return entity.instance;
                else
                    Remove<T>(endpoint);
                }
            
            return default(T);
        }

        public void Remove<T>(string endpoint)
        {
            if (_list.ContainsKey(typeof(T).FullName))
            {
                _list.Remove(typeof(T).FullName);
            }
        }

        private class ChannelEntity
        {
            public string Endpoint { get; set; }
            public DateTime CreateTime { get; set; }
        }

        private class ChannelEntity<T> : ChannelEntity
        {
            public SinacorClientChannel<T> ServiceChannel { get; set; }
            public T instance { get; set; }
        }
    }
}
